﻿namespace UsefulTools.ExtensionMethods
{
    #region Usings

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.AccessControl;

    #endregion

    public static class Common
    {
        /// <summary>
        /// Casts the object to a type given as a generic parameter.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static T CastTo<T>(this object obj)
        {
            return (T)obj;
        }

        /// <summary>
        /// Checks whether the object is of type given as generic parameter.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool IsAnyOf<T>(this object obj)
        {
            return obj is T;
        }
        /// <summary>
        /// Checks whether the object is of any of the types given as generic parameters.
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool IsAnyOf<T1,T2>(this object obj)
        {
            return obj is T1 || obj is T2 ;
        }
        /// <summary>
        /// Checks whether the object is of any of the types given as generic parameters.
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool IsAnyOf<T1, T2, T3>(this object obj)
        {
            return obj is T1 || obj is T2 || obj is T3;
        }
        /// <summary>
        /// Checks whether the object is of any of the types given as generic parameters.
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <typeparam name="T4"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool IsAnyOf<T1, T2, T3, T4>(this object obj)
        {
            return obj is T1 || obj is T2 || obj is T3 || obj is T4;
        }
        /// <summary>
        /// Checks whether the object is of any of the types given as generic parameters.
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <typeparam name="T4"></typeparam>
        /// <typeparam name="T5"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool IsAnyOf<T1, T2, T3, T4, T5>(this object obj)
        {
            return obj is T1 || obj is T2 || obj is T3 || obj is T4 || obj is T5;
        }
        /// <summary>
        /// Checks whether the object is of any of the types given as generic parameters.
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <typeparam name="T3"></typeparam>
        /// <typeparam name="T4"></typeparam>
        /// <typeparam name="T5"></typeparam>
        /// <typeparam name="T6"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool IsAnyOf<T1, T2, T3, T4, T5, T6>(this object obj)
        {
            return obj is T1 || obj is T2 || obj is T3 || obj is T4 || obj is T5 || obj is T6;
        }

        /// <summary>
        /// Returns the list with a given object as a single item.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static List<T> InList<T>(this T obj) 
        {
            var arr = new List<T>();
            arr.Add(obj);
            return arr;
        }
        /// <summary>
        /// Returns a list with a given object as a single item.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="T2"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static List<T> InList<T, T2>(this T2 obj) where T2 : T
        {
            var arr = new List<T>();
            arr.Add(obj);
            return arr;
        }

        /// <summary>
        /// Returns an array with single item if the condition is true or no items otherwise.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="condition"></param>
        /// <returns></returns>
        public static T[] InArrayIf<T>(this T obj, bool condition)
        {
            if(condition)
            {
                var arr = new T[1];
                arr[0] = obj;
                return arr;
            }
            else
            {
                return new T[0];
            }
        }
        /// <summary>
        /// Returns an array with single item if the predicate returns true or no items otherwise.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public static T[] InArrayIf<T>(this T obj, Func<T,bool> predicate)
        {
            if (predicate(obj))
            {
                var arr = new T[1];
                arr[0] = obj;
                return arr;
            }
            else
            {
                return new T[0];
            }
        }
        /// <summary>
        /// Returns an enumerable with a given object as a single item.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static IEnumerable<T> ToEnumerable<T>(this T obj)
        {
            return obj.InList();
        }

        /// <summary>
        /// Checks whether the given object is equal to any of the given values.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public static bool IsIn<T>(this T obj, params T[] values)
        {
            return values.Contains(obj);
        }


    }
}